限免<Struts2(s2-045)远程命令执行漏洞分析与复现> 实验,如期而至!
古语曰:“言必信,行必果”,做人做事一定要讲究诚信。在Struts2 (S2—045)远程命令执行漏洞爆出来的当天,合天智汇承诺同学们会出相关的实验,今天我们信守承诺,为大家奉上我们的新实验《Struts2 (S2—045)远程命令执行漏洞分析和复现》 ,重点是限时免费三天!!!
跟着小编一起学习这个令人惊悚的漏洞吧~~~
实验简介:
Apache Struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用于创建企业级Java Web
应用的开源MVC框架,主要提供两个版本框架产品: Struts 1和Struts 2。
该漏洞是由于上传功能的异常处理函数没有正确处理用户输入的错误信息。导致远程攻击者可通过发送恶意的数据包,利用该漏洞在受影响服务器上执行任意命令。
实验目的
通过本次实验,了解s2-045漏洞的原理以及修复方法。
实验步骤
步骤一:漏洞分析
首先我们用工具直接对比补丁前后的文件,来找到补丁修改的代码,源码已经放在桌面,一个是有漏洞的版本,一个是修复后的版本。
先解压,然后通过Beyond Compare 4 这个工具来对所有文件进行比对,来找出修改的文件,除了Beyond Compare 4,还可以去github上把官方git仓库clone下来进行对比,这里不再详细介绍。
解压后,先进入STRUTS_2_3_31 目录,然后右击struts-STRUTS_2_3_31目录,选择select left folder for Compare。
然后来到struts-STRUTS_2_3_32 目录,右击struts-STRUTS_2_3_32目录,选择Compareto”struts-STRUTS_2_3_31”来与之前的文件夹里所有文件进行对比。
然后在菜单栏点击 edit,选择Select All或者直接按Ctrl+A。
然后点击菜单栏的Actions,选择Compare Contents。
弹出如下对话框
比较方式选择Binary comparison,把show results dialog 勾选上,然后等待比较完成。
如图,下面显示的红色的为有修改的,一共有57个文件内容不同。
可以看到主要修改的是这三个文件
其他的都是只修改了版本号,还有一个URLValidatorTest.java文件也只修改了一些无关紧要的东西,随便打开这3个文件中的一个看一下,直接双击即可打开对应的文件。
在左边导航栏里,有一块区域是红色,这里就是2个文件不相同的地方,可以直接在导航栏点击红色区域直接调到对应的代码处,可以看到是在buildErrorMessage 函数里面,更新后的版本在调用LocalizedTextUtil.findText 的时候后面的参数发生了变化。其他2个文件修改的内容也类似。
继续跟进LocalizedTextUtil.findText,因为java支持方法重载,所以在找findText的时候可能会有多个findText函数,我们根据这里的传参个数,以及参数的类型,就可以找到这里实际调用的函数,我们可以在xwork-core\src\main\java\com\opensymphony\xwork2\util\LocalizedTextUtil.java里找到这个方法。
在第376行,可以看到该方法的实现。
在该方法的注释里可以看到下面这段话
Message中${}里的代码会被当作OGNL 表达式执行。
在注释里也可以看到当没有message时,通过defaultMessage来获取message,再跟进getDefaultMessage函数,在该函数里调用了TextParseUtil.translateVariables,该方法的源码在xwork-core\src\main\java\com\opensymphony\xwork2\util\TextParseUtil.java 里面,找到translateVariables方法并跟踪,可以看到最终调用com.opensymphony.xwork2.util.OgnlTextParser.evaluate(char[],String, ParsedValueEvaluator, int),导致了ognl命令执行。
分析完了形成原因,然后来看下怎么利用,我们可以查找所有buildErrorMessage 函数的调用,也可以从框架入口开始跟踪输入流。
根据官方的说明以及网上公开的poc,我们选择从框架入口开始跟踪。
Struts2 的默认入口是StrutsPrepareAndExecuteFilter,可以在web.xml里查看,
源码路径为core\src\main\java\org\apache\struts2\dispatcher\ng\filter\StrutsPrepareAndExecuteFilter.java
首先对requests进行了处理,跟进处理函数,在core\src\main\java\org\apache\struts2\dispatcher\Dispatcher.java的wrapRequest的函数里,首先判断content type是否为空,然后判断是不是有multipart/form-data 这个字符串,如果是则建立一个multiPartRequest 的实例,并且建立MultiPartRequestWrapper。
在建立MultiPartRequestWrapper时解析requests。
通过设置struts.multipart.parser的值,可以指定不同的解析类,struts.multipart.parser的值有多个,而默认的是jakarta,在default.properties里面可以看到, 在struts-2.3.31-all\struts-2.3.31\lib 下找到struts2-core-2.3.31.jar包。
default.properties在struts2-core-2.3.31.jar包里面的org\apache\struts2\路径下,如果想查看,可以直接把struts2-core-2.3.31.jar包解压,然后查看如图:
也就是调用了,org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest类的parse方法,可以继续跟进processUpload,最终跟踪到该函数发生了异常,在调用里面可以看到,当处理 multipart 的时候发生了异常,进入了parse的异常分支,然后调用了前面存在漏洞的方法。
所以我们只要构造特殊的content-type值,在该值里面包含OGNL表达式就可以达到远程命令执行了,当然content-type里必须包含multipart/form-data,通过分析我们也知道,并不需要真正的上传文件就可以利用。
步骤二 :漏洞测试
根据已公开的poc,测试自己的主机是否存在漏洞。在本地已经搭建好环境,需要自己开启tomcat,然后访问,能正常访问以后,用poc.py进行测试,在poc里可以看到Content-Type 里包含有multipart/form-data 字符串。
该poc如果运行成功,会在目标主机上执行ipconfig这个命令。
同时在poc目录下,必须存在test.txt,这个文件名和路径可以自行修改,只要保证存在即可。
可以自己测试,使用方法如下:
可以看到成功执行了ipconfig。
步骤三:检查与修复
Web管理员可以查看web目录下/WEB-INF/lib/目录下的struts-core.x.x.jar 文件,本试验中的路径为:C:\Program Files (x86)\Apache Software Foundation\Tomcat 6.0\webapps\S2-045\WEB-INF\lib。如果这个版本在Struts2.3.5 到 Struts2.3.31 以及 Struts2.5 到 Struts2.5.10之间则存在漏洞。下图是本次试验中用到的lib包,可以看到是在受影响范围的。
升级到最新版消除漏洞影响,如果不方便及时升级,可以过滤content-type中的字符来达到临时缓解的效果。
实践是检验真理的唯一标准,赶快跟上小编的步伐,用行动验证你的想象!
关注合天,掌握更多网安技能!